﻿using System;
using System.Collections.Generic;
using System.Text;
using Sinacor.Infra.Common.Exceptions;
using Sinacor.Infra.Service.ExceptionHandling;
using Sinacor.Servico.Bovespa.Comum.ResourceAccess; 
using Sinacor.Servico.Bovespa.Operador.BusinessEntity;
using Sinacor.Servico.Bovespa.Operador.ResourceAccess;
using Sinacor.Servico.Bovespa.Operador.BusinessEntity.Enum;
using Sinacor.Infra.Service.Validation;
using Sinacor.Infra.Service.Common;
using System.Linq;

namespace Sinacor.Servico.Bovespa.Operador.BusinessLogic
{
    public class Operador : BaseBusinessLogic
    {
        private ResourceAccess.Operador _operador;

        #region Constantes de Erro
        private const int ERRO_OPERADOR_OPERADORNAOINFORMADO = 108000; //incluido - eduardo sertorio - 20080215
        private const int ERRO_OPERADOR_PESQUISASEMRESULTADO = 108001; //incluido - eduardo sertorio - 20080215
        private const int ERRO_OPERADOR_OPERADORINVALIDO = 108002; //incluido - eduardo sertorio - 20080215
        private const int ERRO_OPERADOR_OBJETONULO = 109033; //incluído - Márcio Belarmino - Data: 28/01/2009
        private const int ERRO_OPERADOR_CODMEGAJAEXISTE = 109040;
        private const int ERRO_OPERADOR_CODRENDAFIXAJAEXISTE = 109041;
        private const int ERRO_OPERADOR_EXISTEORDEMABERTA = 109039;
        #endregion Constantes de Erro

        #region Construtor
        public Operador()
            : base()
        {
            _operador = new ResourceAccess.Operador();
        }
        #endregion 

        #region ConsultarOperador
        public List<BusinessEntity.Operador> ConsultarOperador()
        {
            return new ResourceAccess.Operador().ConsultarOperador();
        }
        #endregion

        #region AtualizarPreferencias
        /// <summary>
        /// Método AtualizarPreferencias
        /// Autor: Márcio Belarmino
        /// Data: 28/01/2009
        /// Obs: Atualiza preferências do usuário
        /// </summary>
        public void AtualizarPreferencias(BusinessEntity.Preferencias request)
        {
            if (request == null)
                 throw new BusinessException(ERRO_OPERADOR_OBJETONULO);
            else
                new ResourceAccess.Operador().AtualizarPreferencias(request);
        }
        #endregion

        #region ObterPreferencias
        /// <summary>
        /// Método ObterPreferencias
        /// Autor: Márcio Belarmino
        /// Data: 28/01/2009
        /// Obs: Obtém preferências do usuário
        /// </summary>
        /// <param name="CodigoOperador"></param>
        /// <returns>BusinessEntity.Preferencias</returns>
        public BusinessEntity.Preferencias ObterPreferencias(System.Int32 CodigoOperador)
        {
            if (CodigoOperador == null)
                throw new BusinessException(ERRO_OPERADOR_OBJETONULO);
            else
                return new ResourceAccess.Operador().ObterPreferencias(CodigoOperador);
        }
        #endregion

        //

        #region AlterarOperador

        public void AlterarOperador(BusinessEntity.Operador request)
        {
            if (request == null)
                throw new BusinessException(ERRO_OPERADOR_OBJETONULO);
            else
            {
                this.ValidarOperador(request);
                this._operador.AlterarOperador(request);
            }
        }

        #endregion

        #region AlterarOperadores

        public void AlterarOperadores(List<BusinessEntity.Operador> request)
        {
            foreach(BusinessEntity.Operador item in request)
                this.AlterarOperador(item);
        }

        #endregion

        #region AlterarRelacaoCorretoraOperador

        public void AlterarRelacaoCorretoraOperador(BusinessEntity.OrigemAnteriorAtual request)
        {
            if(request == null)
                throw new BusinessException(ERRO_OPERADOR_OBJETONULO);
            else
            {
                this.ValidarRelacaoCorretoraOperador
                    (
                        new BusinessEntity.Origem()
                        {
                            Corretora = request.Atual.Corretora,
                            OperadorOrigem = request.Atual.OperadorOrigem,
                            OperadorReceptor = request.Anterior.OperadorReceptor
                        }
                    );

                this._operador.AlterarRelacaoCorretoraOperador(request);
            }
        }

        #endregion

        #region ConsultarCorretorasRelacionadas

        public List<BusinessEntity.Origem> ConsultarCorretorasRelacionadas(BusinessEntity.Parameter.FiltroCodigoOperador request)
        {
            if (request == null)
            {
                throw new BusinessException(ERRO_OPERADOR_OBJETONULO);
                return null;
            }
            else
                return this._operador.ConsultarCorretorasRelacionadas(request);
        }

        #endregion

        #region ConsultarOperadores

        public List<BusinessEntity.Operador> ConsultarOperadores(BusinessEntity.Parameter.FiltroOperador request)
        {
            if (request == null)
            {
                throw new BusinessException(ERRO_OPERADOR_OBJETONULO);
                return null;
            }
            else
                return this._operador.ConsultarOperadores(request);
        }        

        #endregion

        #region ConsultarSubordinados

        public List<BusinessEntity.Operador> ConsultarSubordinados(BusinessEntity.Parameter.FiltroCodigoOperador request)
        {
            if (request == null)
            {
                throw new BusinessException(ERRO_OPERADOR_OBJETONULO);
                return null;
            }
            else
                return this._operador.ConsultarSubordinados(request);
        }

        #endregion

        #region ConsultarIdentificacaoSubordinados

        public List<BusinessEntity.Operador> ConsultarIdentificacaoSubordinados(BusinessEntity.Parameter.FiltroCodigoOperador request)
        {
            // Carrega a lista dos subordinados de um operador específico.
            // Esta lista será utilizada para especificar no DataGrid Subordinados,
            // quais são os operadores subordinados ao operador selecionado no DataGrid Operadores.
            List<BusinessEntity.Operador> listaSubordinado = this.ConsultarSubordinados(new BusinessEntity.Parameter.FiltroCodigoOperador() { Valor = request.Valor });

            // Carrega a lista de operadores
            List<BusinessEntity.Operador> listaOperadores = this._operador.ConsultarOperadores
                                                            (
                                                                new BusinessEntity.Parameter.FiltroOperador
                                                                {
                                                                    CodigoOperador = null,
                                                                    CodigoOperadorMegaBolsa = null,
                                                                    CodigoOperadorRendaFixa = null,
                                                                    IndicadorDesprezaOperadorSinalOfertasMegaBolsa = null,
                                                                    IndicadorOperadorHomeBroker = null,
                                                                    IndicadorPontaMesa = null,
                                                                    LoginOperador = null,
                                                                    NomeOperador = null
                                                                }
                                                            );

            // Remove o operador selecionado da lista de subordinados
            listaOperadores.Remove(listaOperadores.First(x => x.CodigoOperador == request.Valor));

            // Identifica quais operadores são subordinados
            foreach (BusinessEntity.Operador item in listaOperadores)
                item.Subordinado = listaSubordinado.FirstOrDefault(x => x.CodigoOperador == item.CodigoOperador) != null;

            return listaOperadores.OrderByDescending(x => x.Subordinado).ToList();
        }

        #endregion

        #region ExcluirOperador

        public void ExcluirOperador(BusinessEntity.Parameter.FiltroCodigoOperador request)
        {
            if (request == null)
                throw new BusinessException(ERRO_OPERADOR_OBJETONULO);
            else
            {
                // Verifica se existe ordem aberta no dia para o operador
                if (this._operador.ConsultarQuantidadeOrdensDiaria(request) > 0)
                    throw new BusinessException(ERRO_OPERADOR_EXISTEORDEMABERTA);

                // Verifica se existe ordem aberta no histórico do operador
                if (this._operador.ConsultarQuantidadeOrdensHistorico(request) > 0)
                    throw new BusinessException(ERRO_OPERADOR_EXISTEORDEMABERTA);

                // Se possui Kernel+                                
                // exclui todos os seus relacionamentos na tabela Origem de Corretoras e Operadores
                if (request.Kernel)
                    this._operador.ExcluirTodosRelacionamentosCorretoraOperador(request);

                // Exclui o operador
                this._operador.ExcluirOperador(request);
            }
        }

        #endregion

        #region ExcluirOperadores

        public void ExcluirOperadores(List<BusinessEntity.Parameter.FiltroCodigoOperador> request)
        {
            foreach (BusinessEntity.Parameter.FiltroCodigoOperador item in request)
                this.ExcluirOperador(item);
        }

        #endregion

        #region ExcluirRelacaoCorretoraOperador

        public void ExcluirRelacaoCorretoraOperador(BusinessEntity.Origem request)
        {
            if (request == null)
                throw new BusinessException(ERRO_OPERADOR_OBJETONULO);
            else
                this._operador.ExcluirRelacaoCorretoraOperador(request);
        }

        #endregion

        #region ExcluirRelacaoCorretoraOperador

        public void ExcluirRelacoesCorretoraOperador(List<BusinessEntity.Origem> request)
        {
            foreach (BusinessEntity.Origem item in request)
                this.ExcluirRelacaoCorretoraOperador(item);
        }

        #endregion        

        #region ExcluirSubordinado

        public void ExcluirSubordinado(BusinessEntity.OperadorXSubordinado request)
        {
            if (request == null)
                throw new BusinessException(ERRO_OPERADOR_OBJETONULO);
            else
                this._operador.ExcluirSubordinado(request);
        }

        #endregion

        #region ExcluirSubordinados

        public void ExcluirSubordinados(BusinessEntity.OperadorXSubordinados request)
        {
            foreach(Int32 item in request.Subordinados)
                this.ExcluirSubordinado(new OperadorXSubordinado { CodigoOperador = request.CodigoOperador, CodigoSubordinado = item });
        }

        #endregion

        #region ExcluirTodosRelacionamentosCorretoraOperador

        public void ExcluirTodosRelacionamentosCorretoraOperador(BusinessEntity.Parameter.FiltroCodigoOperador request)
        {
            if (request == null)
                throw new BusinessException(ERRO_OPERADOR_OBJETONULO);
            else
                this._operador.ExcluirTodosRelacionamentosCorretoraOperador(request);
        }

        #endregion

        #region ExcluirTodosSubordinados

        public void ExcluirTodosSubordinados(BusinessEntity.Parameter.FiltroCodigoOperador request)
        {
            if (request == null)
                throw new BusinessException(ERRO_OPERADOR_OBJETONULO);
            else
                this._operador.ExcluirTodosSubordinados(request);
        }

        #endregion

        #region IncluirOperador

        public void IncluirOperador(BusinessEntity.Operador request)
        {
            if (request == null)
                throw new BusinessException(ERRO_OPERADOR_OBJETONULO);
            else
            {
                // Inclui usuário comum como operador
                this._operador.IncluirOperador(request);
                
                // Inclui operador como subordinado dele mesmo
                this._operador.IncluirSubordinado(new BusinessEntity.OperadorXSubordinado { CodigoOperador = request.CodigoOperador.Value, CodigoSubordinado = request.CodigoOperador.Value });

                // Inclui preferências padrões para o novo operador
                this._operador.IncluirPreferencias
                    (
                        new BusinessEntity.Preferencias
                        {
                            CodigoOperador = request.CodigoOperador.Value,
                            Mercado = TipoMercado.Vista,
                            Ordem = TipoOrdem.Administrada,
                            Bolsa = "1",
                            OrdemModoInsert = false,
                            PopulaLoteAutomaticamenteAposInsercao = false,
                            PopulaLoteAutomaticamenteAposPreBoleto = false,
                            OrdenaDigitacaoDecrescente = false,
                            UtilizaDataPreBoleto = false
                        }
                    );
            }
        }

        #endregion

        #region IncluirOperadores

        public void IncluirOperadores(List<BusinessEntity.Operador> request)
        {
            foreach(BusinessEntity.Operador item in request)
                this.IncluirOperador(item);
        }

        #endregion

        #region IncluirRelacaoCorretoraOperador

        public void IncluirRelacaoCorretoraOperador(BusinessEntity.Origem request)
        {
            if (request == null)
                throw new BusinessException(ERRO_OPERADOR_OBJETONULO);
            else
            {
                this.ValidarRelacaoCorretoraOperador(request);
                this._operador.IncluirRelacaoCorretoraOperador(request);
            }
        }

        #endregion        

        #region IncluirPreferencias

        public void IncluirPreferencias(BusinessEntity.Preferencias request)
        {
            if (request == null)
                throw new BusinessException(ERRO_OPERADOR_OBJETONULO);
            else
                this._operador.IncluirPreferencias(request);
        }

        #endregion

        #region IncluirSubordinado

        public void IncluirSubordinado(BusinessEntity.OperadorXSubordinado request)
        {
            if(request == null)
               throw new BusinessException(ERRO_OPERADOR_OBJETONULO);
            else
               this._operador.IncluirSubordinado(request);
        }

        #endregion

        #region IncluirSubordinados

        public void IncluirSubordinados(BusinessEntity.OperadorXSubordinados request)
        {
            foreach (Int32 item in request.Subordinados)
                this.IncluirSubordinado(new OperadorXSubordinado { CodigoOperador = request.CodigoOperador, CodigoSubordinado = item });
        }

        #endregion

        #region ExecutarTransacoesRelacaoCorretoraOperador

        public void ExecutarTransacoesRelacaoCorretoraOperador(List<BusinessEntity.Origem> listaInclusao, List<BusinessEntity.OrigemAnteriorAtual> listaAlteracao, List<BusinessEntity.Origem> listaExclusao)
        {
            foreach (BusinessEntity.Origem item in listaInclusao)
                this.IncluirRelacaoCorretoraOperador(item);

            foreach (BusinessEntity.OrigemAnteriorAtual item in listaAlteracao)
                this.AlterarRelacaoCorretoraOperador(item);

            foreach (BusinessEntity.Origem item in listaExclusao)
                this.ExcluirRelacaoCorretoraOperador(item);
        }

        #endregion

        #region ValidarOperador

        public void ValidarOperador(BusinessEntity.Operador request)
        {
            // Verificar se já existe operador mega bolsa
            if (request.CodigoOperadorMegaBolsa.HasValue)
            {
                List<BusinessEntity.Operador> operadores = this._operador.ConsultarOperadores(new BusinessEntity.Parameter.FiltroOperador { CodigoOperadorMegaBolsa = request.CodigoOperadorMegaBolsa }).FindAll(delegate(BusinessEntity.Operador op) { return op.CodigoOperador != request.CodigoOperador; });
                if (operadores.Count > 0)
                    throw new BusinessException(ERRO_OPERADOR_CODMEGAJAEXISTE);
            }

            // Verifica se já existe operador renda fixa
            if (!String.IsNullOrEmpty(request.CodigoOperadorRendaFixa))
            {
                List<BusinessEntity.Operador> operadores = this._operador.ConsultarOperadores(new BusinessEntity.Parameter.FiltroOperador { CodigoOperadorRendaFixa = request.CodigoOperadorRendaFixa }).FindAll(delegate(BusinessEntity.Operador op) { return op.CodigoOperador != request.CodigoOperador; });
                if (operadores.Count > 0)
                    throw new BusinessException(ERRO_OPERADOR_CODRENDAFIXAJAEXISTE);
            }

        }

        #endregion

        #region ValidarRelacaoCorretoraOperador

        public void ValidarRelacaoCorretoraOperador(BusinessEntity.Origem request)
        {
            SinacorValidation validation = new SinacorValidation();

            validation.AddValidation<BusinessEntity.Origem>(request);

            validation.Validate();

            validation = null;

            // Verifica se o relacionamento corretora operador já existe
            if (this._operador.VerificarExistenciaCorretoraRelacionada(request))
                throw new BusinessException(109044);
        }

        #endregion
    }
}
